package cn.pconline.autoclub.service;

import cn.pconline.autoclub.entity.Club;
import cn.pconline.autoclub.entity.ClubMember;
import cn.pconline.autoclub.entity.EntityWithUserProp;
import cn.pconline.autoclub.entity.SendMsg;
import cn.pconline.autoclub.entity.User;
import cn.pconline.autoclub.util.DateUtils;
import cn.pconline.autoclub.util.Pager;
import cn.pconline.autoclub.util.club.ComboCnd;
import cn.pconline.passport2.Account;
import cn.pconline.passport2.Passport;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.lang.StringUtils;
import org.gelivable.dao.GeliDao;
import org.gelivable.dao.GeliOrm;
import org.gelivable.dao.SqlBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.ResultSetExtractor;

/**
 *
 * @author wanganning
 */
public class UserService {

    @Autowired
    private GeliDao geliDao;
    @Autowired
    private GeliOrm geliOrm;
    @Autowired
    private PagerService pagerService;
    @Autowired
    private MemberService memberService;
    @Autowired
    private IntfService intfService;
    @Autowired
    private Passport passport;

    /**
     * 查找用户
     *
     * @param uid
     * @return
     */
    public User findUser(long uid) {
        try {
            return geliDao.find(User.class, uid);
        } catch (EmptyResultDataAccessException e) {
            return null;
        }
    }

    /**
     * 创建用户
     *
     * @param user
     * @return
     */
    public long createUser(User user) {
        return geliDao.create(user);
    }

    /**
     * 更新用户
     *
     * @param user
     * @return
     */
    public int updateUser(User user) {
        return geliDao.update(user);
    }

    public int updateUser(User user, String fields) {
        return geliDao.update(user, fields);
    }

    /**
     * 设置Vip
     *
     * @param userId
     * @param vipInfo
     */
    public void setVip(long userId, String vipInfo) {
        User user = findUser(userId);
        if (user != null) {
            user.setVip(1);
            user.setVipInfo(vipInfo);
            geliDao.update(user, "vip,vip_info");
        }
    }

    /**
     * 设置Vip
     *
     * @param user
     * @param vipInfo
     */
    public void setVip(User user, String vipInfo) {
        if (user != null) {
            System.out.println("set vip user： " + user.getUid() + " - " + vipInfo);
            user.setVip(1);
            user.setVipInfo(vipInfo);
            geliDao.update(user, "vip,vip_info");
        }
    }

    /**
     * 取消车主认证
     *
     * @param userId
     */
    public void cancelVip(long userId) {
        User user = findUser(userId);
        if (user != null) {
            user.setVip(0);
            user.setVipInfo(null);
            geliDao.update(user, "vip,vip_info");
        }
    }

    /**
     * 批量预读车友会成员信息中的用户信息
     *
     * @param members 一批车友会成员
     * @return 填充用户信息之后的
     */
    @SuppressWarnings("rawtypes")
    public List loadTransientUsers(List<? extends EntityWithUserProp> entities) {
        if (entities == null || entities.isEmpty()) {
            return entities;
        }
        long[] ids = new long[entities.size()];
        for (int i = 0; i < entities.size(); i++) {
            EntityWithUserProp entity = entities.get(i);
            if (entity != null) {
                ids[i] = entity.getUid();
            }
        }
        List<User> users = geliDao.list(User.class, ids);
        for (int i = 0; i < entities.size(); i++) {
            EntityWithUserProp entity = entities.get(i);
            if (entity != null) {
                entity.setUser(users.get(i));
            }
        }
        return entities;
    }

    /**
     * 根据用户名查找用户
     *
     * @Nullable
     * @param username 用户名
     * @return
     */
    public User findByName(String username) {
        String sql = "SELECT * FROM ac_user WHERE username=?";
        return geliDao.findFirst(User.class, sql, username);
    }

    /**
     * 根据车友会ID和会员ID查询用户ID
     *
     * @param clubId
     * @param memberId
     * @return
     */
    public User getUserByMemberId(long memberId) {
        if (memberId < 1) {
            return null;
        }
        SqlBuilder sql = new SqlBuilder();
        sql.appendSql(" select user_id from ac_member_info ");
        sql.appendSql(" where id = ").appendValue(memberId);
        List<User> list;
        User user = null;
        try {
            list = geliDao.list(User.class, sql.getSql(), sql.getValues());
        } catch (EmptyResultDataAccessException e) {
            return null;
        }
        if (list != null && !list.isEmpty()) {
            user = list.get(0);
        }
        return user;
    }

    /**
     * 根据ID或者名称查询用户列表
     *
     * @param userId
     * @param name
     * @param orderDirection
     * @param orderField
     * @return
     */
    public Pager<User> getUserByIdOrName(long userId, String name, int pageNo, int pageSize, String orderField, String orderDirection) {
        SqlBuilder sql = new SqlBuilder();
        sql.appendSql(" select user_id from ").appendSql(geliOrm.getTableName(User.class)).appendSql(" where 1=1 ");
        if (userId > 0) {
            sql.appendSql(" and user_id =").appendValue(userId);
        }
        if (StringUtils.isNotBlank(name)) {
            sql.appendSql(" and username = ").appendValue(name);
        }
        if (StringUtils.isNotBlank(orderField) && StringUtils.isNotBlank(orderDirection)) {
            sql.appendSql(" order by ").appendSql(orderField).appendSql(" ").appendSql(orderDirection);
        }
        return pagerService.pager(User.class, sql, pageNo, pageSize);
    }

    public List<User> initCacheUser() {
        SqlBuilder sql = new SqlBuilder();
        sql.appendSql(" select user_id from ").appendSql(geliOrm.getTableName(User.class));
        return geliDao.list(User.class, sql.getSql(), sql.getValues());
    }

    /**
     * 获取加入车友会的所有会员
     *
     * @return
     */
    public List<User> findAllClubUser() {
        SqlBuilder sql = new SqlBuilder();
        sql.appendSql("select user_id from ").appendSql(geliOrm.getTableName(User.class)).appendSql(" where joined_club_count>0");
        return geliDao.list(User.class, sql.getSql());
    }

    /**
     * 获取某车友会的所有会员（除指定userId除外）
     *
     * @param clubId
     * @param userId
     * @return
     */
    public List<User> findAllUser(long clubId, long userId) {
        SqlBuilder sql = new SqlBuilder();
        sql.appendSql("select user_id from ").appendSql(geliOrm.getTableName(ClubMember.class));
        sql.appendSql(" where club_id = ").appendValue(clubId);
        sql.appendSql(" and user_id != ").appendValue(userId);
        return geliDao.list(User.class, sql.getSql(), sql.getValues());
    }

    /**
     * 根据坐标查询附近用户
     *
     * @param longitude 经度
     * @param latitude 纬度
     * @param scope 范围
     * @param userId除了此ID以外的（即自己的位置除外）
     * @return
     */
    public Pager<User> findUserByPosition(double longitude, double latitude, int scope, int pageNo, int pageSize, long userId) {
        double minLongitude = longitude - scope;
        double minLatitude = latitude - scope;
        double maxLongitude = longitude + scope;
        double maxLatitude = latitude + scope;
        SqlBuilder sql = new SqlBuilder();
        sql.appendSql("select user_id from ").appendSql(geliOrm.getTableName(User.class)).appendSql(" where longitude>=").appendValue(minLongitude)
                .appendSql(" and longitude<=").appendValue(maxLongitude).appendSql(" and latitude>=").appendValue(minLatitude).appendSql(" and  latitude<=").appendValue(maxLatitude);
        Pager<User> pager = pagerService.pager(User.class, sql, pageNo, pageSize);
        if (userId > 0) {
            if (pager != null && pager.getResultList() != null) {
                List<User> rsList = new ArrayList<User>();
                for (User u : pager.getResultList()) {
                    if (userId != u.getUid()) {
                        rsList.add(u);
                    } else {
                        pager.setTotal(pager.getTotal() - 1);
                    }
                }
                pager.setResultList(rsList);
            }
        }
        return pager;
    }

    /**
     * 根据同步条件获取加入车友会的会员
     *
     * @param sendAll
     * @param areaAndBrandCombineStr
     * @return
     */
    public List<User> findClubUser(int sendAll, Object[] clubIds, List<ComboCnd> cnds) {
        SqlBuilder sql = new SqlBuilder();
        sql.appendSql("select u.user_id as user_id from ").appendSql(geliOrm.getTableName(User.class) + " u ,");
        sql.appendSql(geliOrm.getTableName(Club.class) + " c ,");
        sql.appendSql(geliOrm.getTableName(ClubMember.class) + " m ");
        sql.appendSql(" where u.joined_club_count>0 and u.user_id = m.user_id and m.club_id=c.club_id ");
        if (sendAll == SendMsg.SCOPE_CERTIFICATION_OWNER) {//1-认证车主
            sql.appendSql(" and u.vip = ").appendValue(1);
        } else if (sendAll == SendMsg.SCOPE_NO_CERTIFICATION_OWNER) {//0-非认证车主
            sql.appendSql(" and u.vip = ").appendValue(0);
        } else if (sendAll == SendMsg.SCOPE_VICE_CHAIRMAN) {//副会长|会长
            sql.appendSql("  and ( m.admin_type = ").appendValue(ClubMember.VICE_ADMIN);
            sql.appendSql(" or m.admin_type = ").appendValue(ClubMember.ADMIN).appendSql(")");
        } else if (sendAll == SendMsg.SCOPE_CHAIRMAN) {//会长
            sql.appendSql("  and m.admin_type = ").appendValue(ClubMember.ADMIN);
        }
        if (clubIds != null) {
            sql.appendSql(" and c.club_id in ").appendValues(clubIds);
        }
        if (cnds != null && !cnds.isEmpty()) {
            sql.appendSql(" and ( 1!=1 ");
            for (ComboCnd cnd : cnds) {//遍历每组or条件组合
                sql.appendSql(" or (1=1 ");
                if (cnd.getCityId() > 0) {
                    sql.appendSql(" and c.city_id=").appendValue(cnd.getCityId());
                }
                if (cnd.getProvinceId() > 0) {
                    sql.appendSql(" and c.province_id=").appendValue(cnd.getProvinceId());
                }
                if (cnd.getBrandId() > 0) {
                    sql.appendSql(" and c.brand_id=").appendValue(cnd.getBrandId());
                }
                if (cnd.getSeriesId() > 0) {
                    sql.appendSql(" and c.series_id=").appendValue(cnd.getSeriesId());
                }
                if (cnd.getLevelId() >= 0) {
                    sql.appendSql(" and c.level_id=").appendValue(cnd.getLevelId());
                }
                if (cnd.getThemeId() > 0) {
                    sql.appendSql(" and c.theme_id=").appendValue(cnd.getThemeId());
                }
                if (cnd.getClubId() > 0) {
                    sql.appendSql(" and c.club_id=").appendValue(cnd.getClubId());
                }
                sql.appendSql(") ");

            }
            sql.appendSql(" ) ");
        }
        return geliDao.list(User.class, sql.getSql(), sql.getValues());
    }

    /**
     * 根据坐标查询附近用户,包括自己的位置在内
     *
     * @param longitude
     * @param latitude
     * @param scope
     * @param pageNo
     * @param pageSize
     * @return
     */
    public Pager<User> findUserByPosition(double longitude, double latitude, int scope, int pageNo, int pageSize) {
        return findUserByPosition(longitude, latitude, scope, pageNo, pageSize, 0L);
    }

    public int updateJoinedClubCount(User user) {
        int count = memberService.countMemberByUid(user.getUid());
        if (count != user.getJoinedClubCount()) {
            user.setJoinedClubCount(count);
            geliDao.update(user, "joined_club_count");
        }
        return user.getJoinedClubCount();
    }

    /**
     * 根据坐标查询附近用户（所有用户）
     *
     * @param longitude 经度
     * @param latitude 纬度
     * @param scope 范围
     * @param userId除了此ID以外的（即自己的位置除外）
     * @return 返回List
     */
    public List<User> findUserByPositionList(double longitude, double latitude, double scope, long userId) {
        double minLongitude = longitude - scope;
        double minLatitude = latitude - scope;
        double maxLongitude = longitude + scope;
        double maxLatitude = latitude + scope;
        SqlBuilder sql = new SqlBuilder();
        sql.appendSql("select user_id,longitude,latitude from ").appendSql(geliOrm.getTableName(User.class)).appendSql(" where longitude>=").appendValue(minLongitude)
                .appendSql(" and longitude<=").appendValue(maxLongitude).appendSql(" and latitude>=").appendValue(minLatitude)
                .appendSql(" and  latitude<=").appendValue(maxLatitude);
        List<User> list = geliDao.getJdbcTemplate().query(sql.getSql(), sql.getValues(), new ResultSetExtractor<List<User>>() {
            @Override
            public List<User> extractData(ResultSet rs) throws SQLException, DataAccessException {
                List<User> list = new ArrayList();
                while (rs.next()) {
                    User u = new User();
                    u.setUid(rs.getLong("user_id"));
                    u.setLatitude(rs.getDouble("latitude"));
                    u.setLongitdue(rs.getDouble("longitude"));
                    list.add(u);
                }
                return list;
            }
        });
        if (userId > 0) {//过滤userId
            List<User> rsList = new ArrayList<User>();
            for (User u : list) {
                if (userId != u.getUid()) {
                    rsList.add(u);
                }
            }
            return rsList;
        }
        return list;
    }

    /**
     * 先从本地数据库获取昵称，获取不到，再去个人中心获取
     *
     * @param uid
     */
    public String getNickNameByUserId(long uid) {
        User u = findUser(uid);
        if (u != null && StringUtils.isNotBlank(u.getNickname())) {
            return u.getNickname();
        } else {
            try {
                return intfService.getNickNameByUserId(uid);
            } catch (Exception exception) {
                return "";
            }
        }
    }

    public User authUser(long userId) {
        User nUser = findUser(userId);
        if (nUser == null) {
            nUser = new User();
            Account account = passport.getAccount(userId);
            nUser.setUid(account.getAccountId());
            nUser.setUsername(account.getAccountName());
            nUser.setCreateAt(DateUtils.getNow());
            nUser.setEmail(account.getEmail());
            nUser.setPhone(account.getMobile());
            String nickname = null;
            try {
                nickname = getNickNameByUserId(userId);
            } catch (Exception e) {
                System.err.println("Retrieve nickname error:uid=" + account.getAccountId());
            }
            nUser.setNickname(nickname);
            createUser(nUser);
        }
        return nUser;
    }
}
